/*
    Dominate 3D - A cube-based game of life

    Copyright (C) 2007, Craig H. Miller (kidmosey@gmail.com)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>

#include "tga.h"
#include "targa.h"

//static CTGA::TGA tga;     // TGA image data

const unsigned char uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0};	// Uncompressed TGA Header
const unsigned char cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0};	// Compressed TGA Header

int CTGA::Load(const char *fname)				// Load a TGA file
{
    //ASSERT(this->GetFilename());

    tga_image *img = tga_read(fname);
    //assert(img);

    this->data = img->data;
    this->width = img->width;
    this->height = img->height;
    this->bpp = img->bits_per_pixel/8;

    return TGA_OK;
/*
    char tgaheader[12];									// TGA header
	FILE *fTGA = fopen(this->GetFilename(), "rb");								// Open file for reading

	if(fTGA == NULL)											// If it didn't open....
		return TGA_ERROR_FILEOPEN;														// Exit function

	if(fread(&tgaheader, sizeof(tgaheader), 1, fTGA) == 0)					// Attempt to read 12 byte header from file
	{
		if(fTGA != NULL)													// Check to seeiffile is still open
			fclose(fTGA);													// If it is, close it

		return TGA_ERROR_BADHEADER;														// Exit function
	}

    int result = InitStructures(fTGA);
    if (result != TGA_OK)
    {
            fclose(fTGA);
            return result;
    }

	if(memcmp(uTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)				// See if header matches the predefined header of
	{																		// an Uncompressed TGA image
		LoadUncompressedTGA(fTGA);						// If so, jump to Uncompressed TGA loading code
	}
	else if(memcmp(cTGAcompare, &tgaheader, sizeof(tgaheader)) == 0)		// See if header matches the predefined header of
	{																		// an RLE compressed TGA image
		LoadCompressedTGA(fTGA);							// If so, jump to Compressed TGA loading code
	}
	else																	// If header matches neither type
	{
		fclose(fTGA);
		return TGA_ERROR_INVALIDIMAGE;																// Exit function
	}

	fclose(fTGA);
	return TGA_OK;															// All went well, continue on
*/
}
/*
int CTGA::InitStructures(FILE *fTGA)
{
    ASSERT(fTGA != NULL);

	if(fread(tga.header, sizeof(tga.header), 1, fTGA) == 0)					// Read TGA header
	{
		if(fTGA != NULL)													// if file is still open
			fclose(fTGA);													// Close it

		return TGA_ERROR_FILEREAD;
	}

	this->width  = tga.Width  = tga.header[1] * 256 + tga.header[0];					// Determine The TGA Width	(highbyte*256+lowbyte)
	this->height = tga.Height = tga.header[3] * 256 + tga.header[2];					// Determine The TGA Height	(highbyte*256+lowbyte)
	this->bpp    = tga.Bpp	   = tga.header[4];										    // Determine the bits per pixel

	if((tga.Width <= 0) || (tga.Height <= 0) || ((tga.Bpp != 24) && (tga.Bpp !=32)))	// Make sure all information is valid
	{
		if(fTGA != NULL)													// Check if file is still open
			fclose(fTGA);													// If so, close it

		return TGA_ERROR_INVALIDIMAGE;										// Return failed
	}

	tga.bytesPerPixel	= (tga.Bpp / 8);									// Compute the number of BYTES per pixel
	tga.imageSize		= (tga.bytesPerPixel * tga.Width * tga.Height);		// Compute the total amout ofmemory needed to store data
	this->data	        = new unsigned char[tga.imageSize];			// Allocate that much memory

	if (this->data == NULL)											// If no space was allocated
	{
		fclose(fTGA);														// Close the file
		return TGA_ERROR_NOTENOUGHMEMORY;									// Return failed
	}

	return TGA_OK;
}

int CTGA::LoadUncompressedTGA(FILE *fTGA)	// Load an uncompressed TGA (note, much of this code is based on NeHe's
{																			// TGA Loading code nehe.gamedev.net)
	if(fread(this->data, 1, tga.imageSize, fTGA) != tga.imageSize)	// Attempt to read image data
	{
		if (this->data)										// If imagedata has data in it
		{
			delete[] this->data;										// Delete data from memory
		}
		fclose(fTGA);														// Close file
		return TGA_ERROR_FILEREAD;											// Return failed
	}

	// Byte Swapping Optimized By Steve Thomas
	for(unsigned int cswap = 0; cswap < (unsigned int)tga.imageSize; cswap += tga.bytesPerPixel)
	{
		this->data[cswap] ^= this->data[cswap+2] ^=
		this->data[cswap] ^= this->data[cswap+2];
	}

	return TGA_OK;
}

int CTGA::LoadCompressedTGA(FILE *fTGA)		// Load COMPRESSED TGAs
{
	unsigned int pixelcount	= tga.Height * tga.Width;							// Nuber of pixels in the image
	unsigned int currentpixel	= 0;												// Current pixel being read
	unsigned int currentbyte	= 0;												// Current byte
	unsigned char *colorbuffer = new unsigned char [tga.bytesPerPixel];			// Storage for 1 pixel

	do
	{
		unsigned char chunkheader = 0;											// Storage for "chunk" header

		if(fread(&chunkheader, sizeof(unsigned char), 1, fTGA) == 0)				// Read in the 1 byte header
		{
			if(fTGA != NULL)												// If file is open
				fclose(fTGA);												// Close file

			if (this->data)									// If there is stored image data
				delete[] this->data, this->data = 0;									// Delete image data

			return TGA_ERROR_BADHEADER;													// Return failed
		}

		if(chunkheader < 128)												// If the ehader is < 128, it means the that is the number of RAW color packets minus 1
		{																	// that follow the header
			chunkheader++;													// add 1 to get number of following color values
			for(short counter = 0; counter < chunkheader; counter++)		// Read RAW color values
			{
				if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel) // Try to read 1 pixel
				{
					if(fTGA != NULL)						    		// See if file is open
						fclose(fTGA);									// If so, close file

					if (colorbuffer)									// See if colorbuffer has data in it
						delete[] colorbuffer;							// If so, delete it

					if(this->data)										// See if there is stored Image data
						delete[] this->data, this->data = 0;			// If so, delete it too

					return TGA_ERROR_INVALIDIMAGE;														// Return failed
				}
																						// write to memory
				this->data[currentbyte		] = colorbuffer[2];				    // Flip R and B vcolor values around in the process
				this->data[currentbyte + 1	] = colorbuffer[1];
				this->data[currentbyte + 2	] = colorbuffer[0];

				if(tga.bytesPerPixel == 4)												// if its a 32 bpp image
				{
					this->data[currentbyte + 3] = colorbuffer[3];				// copy the 4th byte
				}

				currentbyte += tga.bytesPerPixel;										// Increase thecurrent byte by the number of bytes per pixel
				currentpixel++;															// Increase current pixel by 1

				if(currentpixel > pixelcount)											// Make sure we havent read too many pixels
				{
					if(fTGA != NULL)						    		// See if file is open
						fclose(fTGA);									// If so, close file

					if (colorbuffer)									// See if colorbuffer has data in it
						delete[] colorbuffer;							// If so, delete it

					if(this->data)										// See if there is stored Image data
						delete[] this->data, this->data = 0;			// If so, delete it too

					return TGA_ERROR_INVALIDIMAGE;														// Return failed
				}
			}
		}
		else																			// chunkheader > 128 RLE data, next color reapeated chunkheader - 127 times
		{
			chunkheader -= 127;															// Subteact 127 to get rid of the ID bit
			if(fread(colorbuffer, 1, tga.bytesPerPixel, fTGA) != tga.bytesPerPixel)		// Attempt to read following color values
			{
                if(fTGA != NULL)					   		// See if file is open
                    fclose(fTGA);							// If so, close file

                if (colorbuffer)							// See if colorbuffer has data in it
                    SAFE_DELETE_ARRAY(colorbuffer);			// If so, delete it

                if(this->data)								// See if there is stored Image data
                    SAFE_DELETE_ARRAY(this->data);			// If so, delete it too

				return TGA_ERROR_FILEREAD;															// return failed
			}

			for(short counter = 0; counter < chunkheader; counter++)					// copy the color into the image data as many times as dictated
			{																			// by the header
				this->data[currentbyte		] = colorbuffer[2];					// switch R and B bytes areound while copying
				this->data[currentbyte + 1	] = colorbuffer[1];
				this->data[currentbyte + 2	] = colorbuffer[0];

				if(tga.bytesPerPixel == 4)												// If TGA images is 32 bpp
				{
					this->data[currentbyte + 3] = colorbuffer[3];				// Copy 4th byte
				}

				currentbyte += tga.bytesPerPixel;										// Increase current byte by the number of bytes per pixel
				currentpixel++;															// Increase pixel count by 1

				if(currentpixel > pixelcount)											// Make sure we havent written too many pixels
				{
					if(fTGA != NULL)						    		// See if file is open
						fclose(fTGA);									// If so, close file

					if (colorbuffer)									// See if colorbuffer has data in it
						delete[] colorbuffer;							// If so, delete it

					if(this->data)										// See if there is stored Image data
						delete[] this->data, this->data = 0;			// If so, delete it too

					return TGA_ERROR_INVALIDIMAGE;														// Return failed
				}
			}
		}
	}

	while(currentpixel < pixelcount);													// Loop while there are still pixels left
	fclose(fTGA);																		// Close the file
	return true;																		// return success
}
*/
